﻿using System.IO;
using System.Net.Sockets;

namespace ThePresenter.Net.NetCom
{
	class ClientReceiveDataState
	{
		
		#region Constants

		/// <summary>
		/// Used to determine socket read buffer size
		/// </summary>
		internal const int BUFFER_SIZE = 8096;

		/// <summary>
		/// Size of DATALENGTH field
		/// </summary>
		internal const int DATALENGTH_SIZE = 4;

		#endregion

		
		#region Fields

		/// <summary>
		/// Total size of data to be received
		/// </summary>
		internal int DataSizeTotal = -1;

		/// <summary>
		/// Size of data received in current block
		/// </summary>
		internal int CurrentDataBlockSize = 0;

		/// <summary>
		/// Buffer to receive length to
		/// </summary>
		internal byte[] LengthBuffer = new byte[DATALENGTH_SIZE];

		/// <summary>
		/// Buffer to receive data to
		/// </summary>
		internal byte[] DataBuffer = new byte[BUFFER_SIZE];

		/// <summary>
		/// Data source stream 
		/// </summary>
		internal NetworkStream Stream;

		/// <summary>
		/// MemoryStream containing received data
		/// </summary>
		internal MemoryStream Data = new MemoryStream();

		#endregion

		
		#region Properties

		/// <summary>
		/// Size of data received up until now
		/// </summary>
		internal int DataSizeRecieved
		{
			get
			{
				return (int)this.Data.Position;
			}
		}

		/// <summary>
		/// Size of missing data yet to receive
		/// </summary>
		internal int DataSizeRemaining
		{
			get
			{
				if (this.DataSizeTotal < 0)
					throw new InvalidDataException("Total data size is not set");

				return this.DataSizeTotal - this.DataSizeRecieved;
			}
		}

		#endregion


		#region Constructor

		/// <summary>
		/// Initializes a new instance of the <see cref="ClientReceiveDataState"/> class.
		/// </summary>
		/// <param name="S">The network stream with data.</param>
		internal ClientReceiveDataState(NetworkStream S)
		{
			this.Stream = S;
		}

		#endregion


		#region Methods

		/// <summary>
		/// Resets this instance.
		/// </summary>
		internal void Reset()
		{
			this.DataSizeTotal = -1;
			this.CurrentDataBlockSize = 0;
			this.LengthBuffer = new byte[DATALENGTH_SIZE];
			this.DataBuffer = new byte[BUFFER_SIZE];
			this.Data = new MemoryStream();
		}

		#endregion

	}
}
